#include <iostream>
#include <string>
#include <string.h>
#include <strings.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>          
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>


#include "Task.hpp"
#include "log.hpp"
#include "ThreadPool.hpp"



uint16_t defaultport = 8080;
static std::string defaultip = "0.0.0.0";
static const int gbacklog = 5;

namespace TcpServer
{
    class Server;

    class Context
    {
    public:
       Context(Server* server,int socket):_server(server),_socket(socket)
       {}

       Server* _server;
       int _socket;
    };
    
    class Server
    {
    public:
           Server(const uint16_t& Serverport = defaultport,const std::string& Serverip = defaultip)
           :_Serverport(Serverport),_Serverip(Serverip),_sockfd(-1)
           {}

           void init()
           {
                //穿件套接字，打开文件描述符
                _sockfd = socket(AF_INET,SOCK_STREAM,0);
                if(_sockfd == -1)
                {
                    //打印错误日志，返回
                    logmessage(FATAL,"socket failed");
                    exit(1);
                }
                //打印成功日志
                logmessage(SUCESS,"socket sucess");
                
                //开始建立bind链接
                struct sockaddr_in address;
                bzero(&address,sizeof(address));
                address.sin_family = AF_INET;
                address.sin_port = htons(_Serverport);
                address.sin_addr.s_addr = INADDR_ANY;

                
                int n  = bind(_sockfd,(struct sockaddr*)&address,sizeof(address));
                if(n == -1)
                {
                    logmessage(FATAL,"bind failed");
                    exit(2);
                }
                logmessage(SUCESS,"bind sucess");

                //开始监听
                
                 n  =  listen(_sockfd, gbacklog);
                 if( n < 0)
                 {
                    logmessage(FATAL,"listen failed");
                    exit(3);
                 }
                 logmessage(SUCESS,"listen sucess");
           }

           void start()
           {
                 
               //创建线程池
               // 
               
               ThreadPool<Task>::getInstance();
            
                //对SIGCHLD做了信号忽略处理时，也不会导致僵尸进程的现象               
                //signal(SIGCHLD,SIG_IGN);
                //正式开始工作
                // 1 . accpet建立接收客户端建立新链接
                 while(1)
                 {
                    struct sockaddr_in address;
                    bzero(&address,sizeof(address));
                    socklen_t length = sizeof(address);
                    int sock  = accept(_sockfd,(struct sockaddr*)&address,&length);

                    if(sock == -1)
                    {
                        //logmessage("errno",getpid(),"notarget");
                        continue;
                    }
                    logmessage(SUCESS,"accept sucess");
                    std::cout << "socketfd :" << sock << std::endl;
                    
                    //建立链接成功，可以开始通信了
                    // int n = fork();
                    
                    // if(n == 0)
                    // {
                    //     //子进程一定要关闭从父进程基础来的listen套接字
                    //     close(_sockfd);
                    //     //孙子进程的资源会被操作系统自动回收，所以这样的执行方式才是对的
                    //     //利用孤儿进程，即保证了多个服务器的行动，又保证了进程pid的回收
                    //     if(fork()>0) exit(-1); 
                    //     serverio(sock);
                    //     close(sock);
                    // }

                    //因为父进程是阻塞等待子进程的，所以这是一种脱裤子放屁的玩法
                    //要实现真正的多进程通信，要利用好孤儿进程

                    //爷爷进程直接一秒回收父进程
                    //pid_t  n =  waitpid(n,nullptr,0);
                    // if(n == -1)
                    // {
                    //     logmessage("fatal",getpid(),"waitpid failed");
                    // }
                    // logmessage("sucess",getpid(),"waitpid sucess");

                    //现在开始实现多进程版本的tcp通讯

                    // pthread_t tid;
                    // Context* ctx = new Context(this,sock);
                    // pthread_create(&tid,nullptr,provideServer,(void *)ctx);
                    //线程可不敢乱关文件描述符，因为是公用一套的

                    //到这里了,穿件一个任务push进入进程
                    Task t(sock,serverio);
                    ThreadPool<Task>::getInstance()->push(t);
                    ThreadPool<Task>::getInstance()->run();

                 }

           }

        //    static void* provideServer(void * arvg)
        //    {
        //         pthread_detach(pthread_self());
        //         Context* ctx = static_cast<Context*>(arvg);
        //         //执行服务
        //         // ctx->_server->serverio(ctx->_socket);
        //         serverio(ctx->_socket);
        //         //执行完成后，释放文件描述符,并且释放被new出来了的 ctx
        //         close(ctx->_socket);
        //         delete ctx;
        //    }

          
    private:
       std::string _Serverip;
       uint16_t _Serverport;
       int _sockfd;
    };
}